<?php


/**
 * Notes:
 * PROJECT_NAME : ERP v1.8 重构erp
 * User: 夏鱼儿<397072174@qq.com>
 * Date: 2024/7/20
 * Time: 14:18
 */

namespace app\company\controller\board;

use app\admin\model\Company;
use app\company\controller\Base;
use app\company\model\CompanyOrderStorage;
use app\company\model\DeliverCar;
use app\company\model\Stat;
use app\company\model\Store;
use app\company\model\StoreOrder;
use app\company\model\StoreUser;
use app\company\model\Warehouse;
use app\company\model\WarehouseStorageGoodsLogs;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Response;

class Index extends Base
{


    /**
     * 仓库概况 获取出库 销量前十 分类及 出库金额和入库金额
     * @param array $create_time
     * @param int $limit
     * @return Response
     */
    public function warehouseOverview(array $create_time = [], int $limit = 9): Response
    {
        $field  = 'goods_id,sum(amount) amount';
        $model  = new WarehouseStorageGoodsLogs();
        $sql    = $model->withSearch('create_time', request()->param())->type(2)->gs($this->company_id);
        $amount = 0;
        $list   = $sql->field($field)->where('amount', '>', 0)->group('goods_id')->order('amount desc')->page(1, $limit)->select()->each(function ($item) {
            $item->goods_name = $item->goods()->value('name');
        });
        //计算前9个金额
        if (!$list->isEmpty()) $amount = array_sum(array_column($list->toArray(), 'amount'));

        //其他金额
        $total_amount = WarehouseStorageGoodsLogs::gs($this->company_id)->withSearch('create_time', request()->param())->type(2)->sum('amount');//总销量
        $other_amount = bcsub($total_amount, $amount, 2);
        //总销量
        $in_amount  = WarehouseStorageGoodsLogs::gs($this->company_id)->withSearch('create_time', request()->param())->type(1)->sum('amount');//入库金额
        $out_amount = WarehouseStorageGoodsLogs::gs($this->company_id)->withSearch('create_time', request()->param())->type(2)->sum('amount');//出库金额
        return $this->success('请求成功', compact('list', 'in_amount', 'out_amount', 'total_amount', 'other_amount'));
    }

    /**
     * 仓库商品明细
     * @param int $page
     * @param int $limit
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function warehouseDetail(int $page = 1, int $limit = 10): Response
    {
        $model = new CompanyOrderStorage();
        $field = 'id,company_id,goods_id,goods_rule_id,warehouse_id,supplier_id,quantity,create_time';
        $model = $model->gs($this->company_id)->field($field)->with([
            'goods'      => getWith('id,name'),
            'goods_rule' => getWith('id,spec_name'),
            'warehouse'  => getWith('id,name'),
            'supplier'   => getWith('id,name')
        ])->withSearch('create_time,supplier_id,goods_id', request()->param());
        $count = $model->count();
        $list  = $model->page($page, $limit)->select()->each(function ($item) {
            $item->in_quantity = WarehouseStorageGoodsLogs::gs($this->company_id)->type(1)->goodsRuleId($item->goods_rule_id)->sum('quantity');//入库数量
        });

        return $this->success('请求成功', compact('list', 'count'));
    }

    /**
     * 仓库商品预警
     * @param int $page
     * @param int $limit
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws Exception
     */
    public function warehouseWarning(int $page = 1, int $limit = 10): Response
    {
        $model = new CompanyOrderStorage();
        $field = 'id,company_id,supplier_id,goods_id,goods_rule_id,warehouse_id,warehouse_area_id,quantity,create_time,warehouse_storage_name,production_time,expire_time';
        $model = $model->gs($this->company_id)->field($field)->with([
            'goods'         => getWith('id,name'),
            'goodsRule'     => getWith('id,spec_name'),
            'warehouse'     => getWith('id,name'),
            'warehouseArea' => getWith('id,name'),
            'supplier'      => getWith('id,name')
        ])->withSearch('create_time,goods_id,supplier_id', request()->param());
        $count = $model->count();
        $list  = $model->page($page, $limit)->order('expire_time')->select()->each(function ($item) {
            $item->production_time = setDates($item->production_time);//生产日期
            $item->expire_time     = difTime($item->expire_time);//预警天数
        });

        return $this->success('请求成功', compact('list', 'count'));
    }

    /**
     * 商品销售统计
     * @param int $page
     * @param int $limit
     * @return Response
     */
    public function goodsSales(int $page = 1, int $limit = 10): Response
    {
        $field = 'goods_id,sum(amount) amount';
        $model = new WarehouseStorageGoodsLogs();
        $sql   = $model->withSearch('create_time,goods_id', request()->param())->type(2)->gs($this->company_id);
        $sql   = $sql->field($field)->with(['goods' => getWith('id,name')])->group('goods_id');
        $count = $sql->count();
        $list  = $sql->order('amount desc')->page($page, $limit)->select();
        return $this->success('请求成功', compact('list', 'count'));
    }

    /**
     * 门店销售金额统计
     * @param int $page
     * @param int $limit
     * @return Response
     */
    public function storeSales(int $page = 1, int $limit = 10): Response
    {
        $sql = (new StoreOrder())->alias('o')
                                 ->join(['dt_store' => 's'], 'o.store_id = s.id')
                                 ->join(['dt_store_order_detail' => 'd'], 'o.id = d.store_order_id')
                                 ->field('o.store_id,sum(d.amount) sales_amount,s.name')
                                 ->where('o.company_id', $this->company_id)
                                 ->whereIn('o.order_status', [2, 3, 4]);

        if ($create_time = request()->param('create_time', 0)) {
            $start = strtotime($create_time[0] . ' 00:00:00');
            $end   = strtotime($create_time[1] . ' 23:59:59');
            $sql   = $sql->whereBetweenTime('o.create_time', $start, $end);
        }
        $sql   = $sql->group('o.store_id')->order('sales_amount desc');
        $count = $sql->count();
        $list  = $sql->page($page, $limit)->select();
        return $this->success('请求成功', compact('list', 'count'));
    }

    /**
     * 门店商品销售数量排行
     * @param int $limit
     * @return Response
     */
    public function storeGoodsSales(int $limit = 10): Response
    {
        $field = 'goods_id,sum(amount) quantity';//统计的其实是金额,这样是为了前端不修改
        $model = WarehouseStorageGoodsLogs::gs($this->company_id)->withSearch('create_time', request()->param())->type(2);
        $list  = $model->field($field)->group('goods_id')->order('amount desc')->page(1, $limit)->select()->each(function ($item) {
            $item->goods = $item->goods()->value('name');
        });
        //总销量
        $total = $list->isEmpty() ? 0.00 : bcadd(array_sum(array_column($list->toArray(), 'quantity')),0,2);//统计的其实是金额,这样是为了前端不修改
        return $this->success('请求成功', compact('list', 'total'));
    }

    /**
     * 门店明细
     * @param int $page
     * @param int $limit
     * @return Response
     */
    public function storeDetail(int $page = 1, int $limit = 10): Response
    {
        $field = 'id,name';
        $model = new Store();
        $sql   = $model->field($field)->withSearch('id', request()->param())->gs($this->company_id);
        $sql   = $sql->with(['store_users' => getWith('id,store_id,real_name,mobile', [], 1)]);
        $count = $sql->count();
        $map   = $this->getMap();
        $list  = $sql->page($page, $limit)->select()->each(function ($item) use ($map) {
            $item->order_count  = $item->storeOrders()->where($map)->count();//订单量
            $item->sales_amount = $item->storeOrderDetailSM($map)->sum('amount');//销售额
        });
        return $this->success('请求成功', compact('list', 'count'));
    }

    /**
     * 门店增长量
     * @param array $create_time 开始结束时间
     * @param int $def_num 默认条数
     * @return Response
     * @throws Exception
     */
    public function storeGrowth(array $create_time = [], int $def_num = 7): Response
    {
        $array = [];
        if ($create_time) {
            $time = $create_time[1];
            $num  = difTime(strtotime($create_time[1]), strtotime($create_time[0]));
        } else {
            $time = date('Y-m-d');
            $num  = $def_num;
        }
        for ($i = 0; $i < $num + 1; $i++) {
            $date         = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($time)));
            $start        = strtotime($date);
            $end          = strtotime($date) + 86400;
            $arr['date']  = $date;
            $arr['count'] = Store::gs($this->company_id)->whereBetweenTime('create_time', $start, $end)->count();
            $array[]      = $arr;
        }
        return $this->success('请求成功', array_reverse($array));
    }

    //数字化地图
    public function map(): Response
    {
        $location = Company::where('id', $this->company_id)->value('location');//地图位置
        //仓库 todo 这个逻辑有问题,后期在处理,已找产品确认,先按照销售单统计
        $warehouses = Warehouse::gs($this->company_id)->field('id,name,address,real_name,mobile,long,lat')->select()->each(function ($item) {
            //今天的出库单 就是昨天的销售单
            $item->order_count = StoreOrder::whereDay('create_time', 'yesterday')->gs($this->company_id)->count();
            //总出库单 所有销售订单
            $item->order_count_all = StoreOrder::gs($this->company_id)->count();
        });
        //门店
        $storeModel = store::gs($this->company_id)->field('id,name,address,long,lat');
        $store      = $storeModel->with([
            "storeUsers" => getWith('id,store_id,real_name,mobile', [], 1)
        ])->select()->each(function ($item) {
            $item->order_count     = $item->storeOrders()->whereDay('create_time')->count(); //今天的订单
            $item->order_count_all = $item->storeOrders()->count();//所有订单
        });
        //车辆
        $car = DeliverCar::gs($this->company_id)->field('id,no')->select()->each(function ($item) {
            //todo 没有定位......
            //司机名称 手机号
            //当天任务数 todo 这个以司机还是车辆维度,待定
            //总任务数//
        });
        return $this->success('请求成功', compact('warehouses', 'store', 'car', 'location'));
    }

    /**
     * 每日配送金额统计
     * @param array $create_time
     * @param int $def_num
     * @return Response
     * @throws Exception
     */
    public function deliverMoney(array $create_time = [], int $def_num = 8): Response
    {
        $array = [];
        if ($create_time) {
            $time = $create_time[1];
            $num  = difTime(strtotime($create_time[1]), strtotime($create_time[0]));
        } else {
            $time = date('Y-m-d');
            $num  = $def_num;
        }
        for ($i = 0; $i < $num + 1; $i++) {
            $date = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($time)));
            //每日配送 其实是前一天的销售额
            $yesterday    = date('Y-m-d', strtotime('-1 day', strtotime($date)));
            $start        = strtotime($yesterday);
            $end          = strtotime($yesterday) + 86400;
            $arr['date']  = $date;
            $arr['money'] = WarehouseStorageGoodsLogs::gs($this->company_id)->whereBetweenTime('create_time', $start, $end)->type(2)->sum('amount');
            $array[]      = $arr;
        }
        return $this->success('请求成功', array_reverse($array));
    }

    /**
     * 配送概况
     * @return Response
     */
    public function deliverOverview(): Response
    {
        $deliver_count     = StoreOrder::gs($this->company_id)->whereDay('create_time', 'yesterday')->whereIn('order_status',[3,4])->count();//今日送数
        $deliver_count_all = StoreOrder::gs($this->company_id)->whereIn('order_status',[3,4])->count();//总配送数
        $store_count       = Store::gs($this->company_id)->count();//总门店数
        $store_count_new   = Store::gs($this->company_id)->whereDay('create_time')->count();//今日新增门店数
        $car_count         = DeliverCar::gs($this->company_id)->count();//总车辆数
        $car_count_new     = DeliverCar::gs($this->company_id)->whereDay('create_time')->count();//今日新增车辆数
        return $this->success('请求成功', compact('deliver_count', 'deliver_count_all', 'store_count', 'store_count_new', 'car_count', 'car_count_new'));
    }

    /**
     * 业务员销售额排名
     * @param int $page
     * @param int $limit
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function salesmanRanking(int $page = 1, int $limit = 10): Response
    {
        $model = StoreOrder::gs($this->company_id)->where('salesman_id', '>', 0)->field('store_id,salesman_id')->withSum('storeOrderDetails', 'amount');
        $model = $model->withSearch('create_time,salesman_id', request()->param())->whereIn('order_status',[2,3,4])->group('salesman_id,store_id');
        $count = $model->count();
        $list  = $model->order('store_order_details_sum desc')->page($page, $limit)->select()->each(function ($item) {
            $item->user       = StoreUser::where('id', $item->salesman_id)->field('real_name,mobile')->find();
            $item->store_name = $item->store()->value('name');
        });
        return $this->success('请求成功', compact('list', 'count'));
    }


    /**
     * 业务员区域销售
     * @throws Exception
     */
    public function salesmanAreaSales($create_time = [], $def_num = 7, $limit = 5): Response
    {
        $array = [];
        if ($create_time) {
            $time = $create_time[1];
            $num  = difTime(strtotime($create_time[1]), strtotime($create_time[0]));
        } else {
            $time = date('Y-m-d');
            $num  = $def_num;
        }
        for ($i = 0; $i < $num + 1; $i++) {
            $date        = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($time)));
            $start       = strtotime($date);
            $end         = strtotime($date) + 86400;
            $arr['date'] = $date;
            $model       = StoreOrder::gs($this->company_id)->where('salesman_id', '>', 0)->field('salesman_id')->withSum('storeOrderDetails', 'amount');
            $model       = $model->whereBetweenTime('create_time', $start, $end)->whereIn('order_status',[2,3,4])->group('salesman_id');
            $list        = $model->order('store_order_details_sum desc')->page(1, $limit)->select()->each(function ($item) {
                $item->real_name = StoreUser::where('id', $item->salesman_id)->value('real_name');
            });
            $arr['list'] = $list;
            $array[]     = $arr;
        }
        return $this->success('请求成功', array_reverse($array));
    }

    /**
     * 今日数据统计
     * @param string $date
     * @return Response
     */
    public function dayStat(string $date = ''): Response
    {
        if (!$date) $date = date('Y-m-d');
        $field = 'sales_amount,order_quantity,collection_amount,purchase_amount,purchase_order_quantity,received_amount';
        $now   = Stat::gs($this->company_id)->type(1)->whereDay('create_time', $date)->field($field)->find();
//        $last = Stat::gs($this->company_id)->type(1)->whereDay('create_time', date('Y-m-d',strtotime('-1 day')) )->find();
//        $old = Stat::gs($this->company_id)->type(1)->whereDay('create_time', date('Y-m-d',strtotime('-1 year')) )->find();
        return $this->success('请求成功', compact('now'));
    }

    /**
     * 月度数据统计
     * @param int $year
     * @param int $month
     * @return Response
     */
    public function monthStat(int $year = 0, int $month = 0): Response
    {
        if (!$year) $year = date('Y');
        if (!$month) $month = date('m');
        $field = 'sales_amount,order_quantity,collection_amount,purchase_amount,purchase_order_quantity,received_amount';
        $now   = Stat::gs($this->company_id)->type(3)->where('month', $month)->where('year', $year)->field($field)->find();
        return $this->success('请求成功', compact('now'));
    }

    /**
     * 季度数据统计
     * @param int $year
     * @param int $quarter
     * @return Response
     */
    public function quarterStat(int $year = 0, int $quarter = 0): Response
    {
        if (!$year) $year = date('Y');
        if (!$quarter) $quarter = ceil(date('m') / 3);
        $field = 'sales_amount,order_quantity,collection_amount,purchase_amount,purchase_order_quantity,received_amount';
        $now   = Stat::gs($this->company_id)->type(4)->where('quarter', $quarter)->where('year', $year)->field($field)->find();
        return $this->success('请求成功', compact('now'));
    }

    /**
     * 季度数据统计
     * @param int $year
     * @param int $quarter
     * @return Response
     */
    public function yearStat(int $year = 0, int $quarter = 0): Response
    {
        if (!$year) $year = date('Y');
        $field = 'sales_amount,order_quantity,collection_amount,purchase_amount,purchase_order_quantity,received_amount';
        $now   = Stat::gs($this->company_id)->type(5)->where('year', $year)->field($field)->find();
        return $this->success('请求成功', compact('now'));
    }

    /**
     * 回款统计
     * @throws Exception
     */
    public function collectionStat($create_time = [], $def_num = 7): Response
    {
        $array = [];
        if ($create_time) {
            $time = $create_time[1];
            $num  = difTime(strtotime($create_time[1]), strtotime($create_time[0]));
        } else {
            $time = date('Y-m-d');
            $num  = $def_num;
        }
        for ($i = 0; $i < $num + 1; $i++) {
            $date        = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($time)));
            $arr['date'] = $date;
            $filed       = "received_amount+collection_amount collection_amount,sales_amount";//实收金额 = 回款金额+今日实收金额(数据库中定义的跟外部有差异)
            $arr['list'] = Stat::gs($this->company_id)->type(4)->field($filed)->whereDay('create_time', $date)->find();
            if (!$arr['list']) {
                $arr['list'] = ['collection_amount' => 0, 'sales_amount' => 0];
            }


            $array[] = $arr;
        }
        return $this->success('请求成功', array_reverse($array));
    }

    //回款数据
    public function collectionData(): Response
    {
        //回款总数据
        $collection_amount = Stat::gs($this->company_id)->type(1)->sum('collection_amount');
        $received_amount   = Stat::gs($this->company_id)->type(1)->sum('received_amount');
        $collection_amount = bcadd($collection_amount, $received_amount, 2);
        //销售总数据
        $sales_amount = Stat::gs($this->company_id)->type(1)->sum('sales_amount');
        return $this->success('请求成功', compact('collection_amount', 'sales_amount'));
    }

    /**
     * 获取where
     * @return array[]
     */
    public function getMap(): array
    {
        $map = [['order_status', 'in', [2, 3, 4]]];
        if ($create_time = request()->param('create_time', 0)) {
            $start = strtotime($create_time[0] . ' 00:00:00');
            $end = strtotime($create_time[1] . ' 23:59:59');
            $map[] = ['dt_store_order.create_time', 'between', [$start, $end]];
        }
        return $map;
    }


}